package com.hexiang;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hexiang.domain.OmsOrder;
import com.hexiang.jdbc.OmsOrderJdbcDaoImpl;
import com.hexiang.jpa.repository.OmsOrderRepository;
import com.hexiang.mybatis.mapper.OmsOrderMapper;
import com.hexiang.mybatisplus.mapper.OmsOrderMybatisPlusMapper;
import com.hexiang.spring.dao.JdbcTemplateOmsOrderDaoImpl;
import org.mybatis.spring.annotation.MapperScan;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Spring Boot 应用启动类
 */
@SpringBootApplication(scanBasePackages = {"com.hexiang"})
@MapperScan("com.hexiang.*.mapper")
@State(Scope.Benchmark)
@BenchmarkMode({Mode.AverageTime})
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class SpringBootDaoBenchmarkApplication {

    private static ConfigurableApplicationContext context;
    private static OmsOrderJdbcDaoImpl omsOrderJdbcDaoImpl;
    private static OmsOrderRepository omsOrderRepository;
    private static OmsOrderMapper omsOrderMapper;
    private static OmsOrderMybatisPlusMapper omsOrderMybatisPlusMapper;
    private static JdbcTemplateOmsOrderDaoImpl jdbcTemplateOmsOrderDaoImpl;

    public static final int DATA_SIZE = 10000;

    public static void main(String[] args) throws RunnerException {


        context = SpringApplication.run(SpringBootDaoBenchmarkApplication.class, args);

        omsOrderJdbcDaoImpl = context.getBean("omsOrderJdbcDaoImpl", OmsOrderJdbcDaoImpl.class);
        omsOrderRepository = context.getBean("omsOrderRepository", OmsOrderRepository.class);
        omsOrderMapper = context.getBean("omsOrderMapper", OmsOrderMapper.class);
        omsOrderMybatisPlusMapper = context.getBean("omsOrderMybatisPlusMapper", OmsOrderMybatisPlusMapper.class);
        jdbcTemplateOmsOrderDaoImpl = context.getBean("jdbcTemplateOmsOrderDaoImpl", JdbcTemplateOmsOrderDaoImpl.class);

        Options opts = new OptionsBuilder()
                .include("\\." + SpringBootDaoBenchmarkApplication.class.getSimpleName() + "\\.")
                .warmupIterations(3)
                .measurementIterations(3)
                .forks(0)
                .threads(10)
                .shouldDoGC(true)
                .shouldFailOnError(true)
                .jvmArgs("-server")
                .build();

        new Runner(opts).run();
        System.exit(-1);

    }

    @State(value = Scope.Benchmark)
    public static class Parameters {
        @Param({"10", "20", "50", "100", "200", "500", "1000", "2000", "5000", "10000"})
        String batchSize;
    }

    @Benchmark
    public void queryByJdbc(Parameters parameters) {
        int size = Integer.parseInt(parameters.batchSize);
        List<OmsOrder> list = omsOrderJdbcDaoImpl.queryListByLimit(size);
        assert size == list.size();
    }

    @Benchmark
    public void queryByJpa(Parameters parameters) {
        int size = Integer.parseInt(parameters.batchSize);
        List<OmsOrder> list = omsOrderRepository.findAll(PageRequest.of(0, size, Sort.by("id"))).getContent();
        assert size == list.size();
    }

    @Benchmark
    public void queryByMybatis(Parameters parameters) {
        int size = Integer.parseInt(parameters.batchSize);
        List<OmsOrder> list = omsOrderMapper.queryListByLimit(size);
        assert size == list.size();
    }

    @Benchmark
    public void queryByMybatisPlug(Parameters parameters) {
        int size = Integer.parseInt(parameters.batchSize);
        IPage page = new Page(1, size);
        List<OmsOrder> list = omsOrderMybatisPlusMapper.selectPage(page, null).getRecords();
        assert size == list.size();
    }

    @Benchmark
    public void queryByJdbcTemplate(Parameters parameters) {
        int size = Integer.parseInt(parameters.batchSize);
        List<OmsOrder> list = jdbcTemplateOmsOrderDaoImpl.queryListByLimit(size);
        assert size == list.size();
    }
}
